package top.codingfly.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import top.codingfly.mapper.AreaCodeMapper;
import top.codingfly.mapper.entity.AreaCodeEntity;
import top.codingfly.model.req.AreaCodeMoveReq;
import top.codingfly.model.req.AreaCodeOperateReq;
import top.codingfly.model.resp.AreaCodeTreeResp;
import top.codingfly.model.resp.common.Response;
import top.codingfly.service.IAreaCodeService;
import top.codingfly.service.IRedisLockService;

import javax.annotation.Resource;
import java.util.*;

/**
 * <p>
 * 行政区划表 前端控制器
 * </p>
 * @author author
 * @since 2025-07-18
 */
@RestController
@RequestMapping("/areaCode")
public class AreaCodeController {

    private static final Logger logger = LoggerFactory.getLogger(AreaCodeController.class);

    @Resource
    private IRedisLockService redisLockService;
    private static final String areaCodeUpdateRedisKey = "area-code:update";

    @Resource
    public AreaCodeMapper areaCodeMapper;
    @Resource
    public IAreaCodeService areaCodeService;

    @GetMapping("/test1")
    public Response test1() throws Exception {
        areaCodeMapper.selectTest();
        long start = System.currentTimeMillis();
        areaCodeMapper.maxSort("710602");
        long end = System.currentTimeMillis();
        logger.info("cost time===>>>"+(end-start));

        start = System.currentTimeMillis();
        areaCodeMapper.maxSort(null);
        end = System.currentTimeMillis();
        logger.info("cost time===>>>"+(end-start));

        return Response.success();
    }

    @GetMapping("/list")
    public Response<List<AreaCodeEntity>> test(String parentCode) throws Exception {
        return Response.success(areaCodeMapper.selectListByParentCode(parentCode));
    }

    @PostMapping("/up")
    public Response up(@RequestBody AreaCodeMoveReq moveDto) throws Exception {
        if (StringUtils.isBlank(moveDto.code)) {
            return Response.error("code不允许为空");
        }
        areaCodeService.up(moveDto.getCode());
        return Response.success();
    }

    @PostMapping("/down")
    public Response down(@RequestBody AreaCodeMoveReq moveDto) throws Exception {
        if (StringUtils.isBlank(moveDto.code)) {
            return Response.error("code不允许为空");
        }
        areaCodeService.down(moveDto.getCode());
        return Response.success();
    }

    /**
    @PostMapping("/move")
    public Response move(@RequestBody AreaCodeMoveReq moveDto) throws Exception {
        if (StringUtils.isBlank(moveDto.code)) {
            return Response.error("code不允许为空");
        }
        return Response.success(areaCodeMapper.selectTest());
    }
     */

    @PostMapping("/add")
    public Response add(@RequestBody AreaCodeOperateReq addDto) throws Exception {
        try {
            if (StringUtils.isBlank(addDto.code) || StringUtils.isBlank(addDto.name)) {
                return Response.error("code/name不允许为空");
            }
            if (StringUtils.isNumericSpace(addDto.code)==false) {
                return Response.error("code必须是数字格式");
            }
            boolean getLock = redisLockService.tryLock(areaCodeUpdateRedisKey, 100L, 60 * 60 * 1000L);
            if (getLock == false) {
                return Response.error("其他人正在修改");
            }
            Integer sort = 1;
            AreaCodeEntity entity = new AreaCodeEntity();
            if (StringUtils.isNotBlank(addDto.getParentCode())) {
                AreaCodeEntity parent = areaCodeMapper.selectOne(new LambdaQueryWrapper<AreaCodeEntity>().eq(AreaCodeEntity::getParentCode, addDto.getParentCode()).last(" LIMIT 1 "));
                Assert.isTrue(parent!=null, "父节点:"+addDto.getParentCode()+"不存在");
                sort = areaCodeMapper.maxSort(addDto.getParentCode());
                entity.setDepth(parent.getDepth()+1);
                entity.setParentCode(addDto.getParentCode());
            } else {
                sort = areaCodeMapper.maxSort(null);
                entity.setParentCode(null);
                entity.setDepth(1);
            }
            entity.setCode(addDto.getCode());
            entity.setName(addDto.getName());
            entity.setSort(sort);
            entity.setCreateTime(new Date());
            entity.setUpdateTime(new Date());
            entity.setIsDeleted(0);
            areaCodeMapper.insert(entity);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return Response.error(e.getMessage());
        } finally {
            redisLockService.releaseLock(areaCodeUpdateRedisKey);
        }
        return Response.success();
    }

    @PostMapping("/update")
    public Response update(@RequestBody AreaCodeOperateReq updateDto) throws Exception {
        if (StringUtils.isBlank(updateDto.code) || StringUtils.isBlank(updateDto.name)) {
            return Response.error("code/name不允许为空");
        }
        AreaCodeEntity entity = areaCodeMapper.selectOne(new LambdaQueryWrapper<AreaCodeEntity>().eq(AreaCodeEntity::getCode, updateDto.code).last(" LIMIT 1 "));
        Assert.isTrue(entity!=null, "节点:"+entity.getParentCode()+"不存在");
        entity.setName(updateDto.getName());
        entity.setUpdateTime(new Date());
        areaCodeMapper.updateById(entity);
        return Response.success();
    }

    @GetMapping("/tree")
    public Response<List<AreaCodeTreeResp>> tree() throws Exception {
        List<Integer> depths = Arrays.asList(1,2,3);
        List<AreaCodeEntity> list = areaCodeMapper.selectList(new LambdaQueryWrapper<AreaCodeEntity>()
                        .in(AreaCodeEntity::getDepth, depths)
                        .eq(AreaCodeEntity::getIsDeleted, 0));
        Map<String, AreaCodeTreeResp> codeMap = new HashMap();
        List<AreaCodeTreeResp> treeList = new ArrayList();
        List<AreaCodeTreeResp> dataList = new ArrayList();
        for (AreaCodeEntity item:list) {
            AreaCodeTreeResp treeItem = new AreaCodeTreeResp();
            treeItem.setId(item.getId());
            treeItem.setCode(item.getCode());
            treeItem.setName(item.getName());
            treeItem.setParentCode(item.getParentCode());
            treeItem.setDepth(item.getDepth());
            treeItem.setSort(item.getSort());
            codeMap.put(item.getCode(), treeItem);
            if (item.getDepth().equals(1)) {
                treeList.add(treeItem);
            }
            dataList.add(treeItem);
        }
        for (AreaCodeTreeResp item:dataList) {
            if (item.getDepth().equals(1)) {
                continue;
            }
            AreaCodeTreeResp parentItem = codeMap.get(item.getParentCode());
            if (parentItem==null) {
                continue;
            }
            parentItem.children.add(item);
        }
        return Response.success(treeList);
    }

}
